package com.conversationboard.api;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.SecurityContext;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.conversationboard.api.xml.XmlUtils;

@Path("api")
public class XmlAPI {

	@Context private SecurityContext securityContext;
	@Context private HttpServletRequest request;


	@POST
	@Consumes(value = "application/xml; charset=UTF-8")
	@Produces(value = "application/xml; charset=UTF-8")
	public String processRequest(String requestXml) throws ApiException {

		StringBuilder responseXml = new StringBuilder("<Responses>");

		try {

			/* Get a list of the types of request embedded in the XML message, then delegate to the relevant
			 * class to process each request, building up a set of responses to be included in within the
			 * <Responses> tags. */

			System.out.println("---- Request --------------------");
			System.out.println(requestXml);
			System.out.println("---------------------------------");

			Document document = XmlUtils.getDocument(requestXml);
			Node requestsNode = document.getChildNodes().item(0);

			if ((requestsNode != null) && (requestsNode.getNodeName().equals("Requests"))) {

				NodeList requestTypes = requestsNode.getChildNodes();

				for (int i = 0; i < requestTypes.getLength(); i++) {

					String requestType = requestTypes.item(i).getNodeName();

					if (requestType.equals("Login")) {
						processLogin(requestXml, responseXml);
					} else if (requestType.equals("RecentlyUpdatedThreads")) {
						processThreads(requestXml, responseXml);
					} else if (requestType.equals("Thread")) {
						processThread(requestXml, responseXml);
					} else if (requestType.equals("Boards")) {
						processBoards(requestXml, responseXml);
					} else if (requestType.equals("SiteInfo")) {
						processSiteInfo(requestXml, responseXml);
					} else if (requestType.equals("Logout")) {
						processLogout(requestXml, responseXml);
					} else if (requestType.equals("UserInfo")) {
						processUserInfo(requestXml, responseXml);
					} else if (requestType.equals("LoggedIn")) {
						processLoggedIn(requestXml, responseXml);
					} else if (requestType.equals("Vote")) {
						processVote(requestXml, responseXml);
					} else if (requestType.equals("Search")) {
						processSearch(requestXml, responseXml);
					} else if (requestType.equals("NewThreads")) {
						processNewThreads(requestXml, responseXml);
					}
				}
			}

		} catch (ParserConfigurationException e) {
			throw new ApiException(e);
		} catch (IOException e) {
			throw new ApiException(e);
		} catch (SAXException e) {
			throw new ApiException(e);
		}

		responseXml.append("</Responses>");

		System.out.println("---- Response --------------------");
		System.out.println(responseXml.toString());
		System.out.println("---------------------------------");

		return responseXml.toString();

	}


	private void processSiteInfo(String requestXml, StringBuilder responseXml) throws ApiException {

		SiteInfoProcessor siteInfoProcessor = new SiteInfoProcessor();
		String response = siteInfoProcessor.processXml(requestXml, null, null);

		responseXml.append(response);
	}


	private void processBoards(String requestXml, StringBuilder responseXml) throws ApiException {

		BoardsProcessor boardsProcessor = new BoardsProcessor();
		String response = boardsProcessor.processXml(requestXml, this.securityContext, null);

		responseXml.append(response);
	}


	private void processLogin(String requestXml, StringBuilder responseXml) throws ApiException {

		LoginProcessor loginProcessor = new LoginProcessor();
		String response = loginProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}


	private void processLogout(String requestXml, StringBuilder responseXml) throws ApiException {

		LogoutProcessor logoutProcessor = new LogoutProcessor();
		String response = logoutProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}


	private void processUserInfo(String requestXml, StringBuilder responseXml) throws ApiException {

		UserInfoProcessor currentUserInfoProcessor = new UserInfoProcessor();
		String response = currentUserInfoProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}


	private void processLoggedIn(String requestXml, StringBuilder responseXml) throws ApiException {

		LoggedInProcessor loggedInProcessor = new LoggedInProcessor();
		String response = loggedInProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}


	private void processThreads(String requestXml, StringBuilder responseXml) throws ApiException {

		RecentlyUpdatedThreadsProcessor threadsProcessor = new RecentlyUpdatedThreadsProcessor();
		String response = threadsProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}


	private void processThread(String requestXml, StringBuilder responseXml) throws ApiException {

		ThreadProcessor threadProcessor = new ThreadProcessor();
		String response = threadProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}


	private void processVote(String requestXml, StringBuilder responseXml) throws ApiException {

		VoteProcessor voteProcessor = new VoteProcessor();
		String response = voteProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}


	private void processSearch(String requestXml, StringBuilder responseXml) throws ApiException {

		SearchProcessor searchProcessor = new SearchProcessor();
		String response = searchProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}


	private void processNewThreads(String requestXml, StringBuilder responseXml) throws ApiException {

		NewThreadsProcessor newThreadsProcessor = new NewThreadsProcessor();
		String response = newThreadsProcessor.processXml(requestXml, this.securityContext, this.request);

		responseXml.append(response);
	}

}
